package common

import (
	"errors"
	"fmt"
	"io"
	"mime"
	"net/http"
	"os"
	"path"
)

const (
	B float64 = 1 << (10 * iota)
	KB
	MB
	GB
)

type Response struct {
	*Request
}

func NewResponse(req *Request) *Response {
	response := &Response{
		Request: req,
	}
	return response
}
func (self *Response) ContentPage() (page *Page, err error) {
	httpClient := self.Request.HttpClient
	httpResp, err := httpClient.Do(self.Request.Request)
	if err != nil {
		if DefaultSpiderConfig.ENABLE_RETRY {
			httpResp, err = func() (*http.Response, error) {
				url := self.URL.String()
				for i := 0; i < DefaultSpiderConfig.RETRY_TIMES; i++ {
					logger.Info("response:retry crawl %s %d times", url, i+1)
					httpResp, err = httpClient.Do(self.Request.Request)
					if err != nil {
						logger.Error("response:%s", err)
					} else {
						return httpResp, nil
					}
				}
				return nil, errors.New(fmt.Sprintf("retry crawl %s all have done", url))
			}()
			if err != nil {
				logger.Error("%s", err)
				return nil, err
			}
		} else {
			logger.Info("%s", err)
			return nil, err
		}

	}
	content_type := httpResp.Header.Get("content-type")
	page = &Page{HttpResp: httpResp}
	if content_type != "" {
		typ, parms, err := mime.ParseMediaType(content_type)
		if err != nil {
			logger.Error("%s", err)
			return nil, err
		}
		page.contentType = typ
		page.charset = parms["charset"]
	}
	return
}
func (self *Response) doRequest(httpReq *http.Request) (*http.Response, error) {
	if self.Request.Request == nil {
		return nil, errors.New("http request is nil")
	}
	httpReq = self.Request.Request
	httpResp, err := self.HttpClient.Do(httpReq)
	if err != nil {
		return nil, err
	}
	return httpResp, nil
}
func (self *Response) Download(savepath, savename string) (err error) {
	httpResp, err := self.doRequest(self.Request.Request)
	if err != nil {
		return
	}
	status := NewHttpStatus(httpResp.StatusCode)
	if status.IsSuccess() {
		body := httpResp.Body
		defer body.Close()
		logger.Info("download#length:%0.2fmb", float64(httpResp.ContentLength)/MB)
		fp := path.Join(savepath, savename) //write file path.
		fw, err := os.OpenFile(fp, os.O_CREATE, os.ModePerm)
		if err != nil {
			return err
		}
		_, err = io.Copy(fw, body)
		if err != nil {
			return err
		}
	} else {
		err = errors.New("response status not success")
	}
	return
}
